package shakespeare;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

public class Shakespeare {
	private static Thread t;
	private static String INPUT_PATH = System.getProperty("user.dir")
			+ "/input";// 输入文件夹
	public static String INPUT_FILETXT = System.getProperty("user.dir")
			+ "/inputfile.txt";// 初始化输出文件
	public static String DICT_FILE = System.getProperty("user.dir")
			+ "/dictfile";// 词典文件
	private static ArrayList<String> filelist = new ArrayList<>();
	private static ArrayList<Double> fileddlist = new ArrayList<>();
	private static ArrayList<ArrayList<WordEntity>> filewordslist = new ArrayList<>();
	private static ArrayList<String> wordslist = new ArrayList<>();
	private static ArrayList<HashMap<String, ArrayList<String>>> wordsInvertedIndex = new ArrayList<>();
	public static String DELIM = ",.!'-:;?| \n	[]()";// 定义分割单词的符号
	public static String[] FWORDS = { "a", "an", "and", "or", "be", "am", "is",
			"are", "of", "it", "he", "she", "the" };
	public static ArrayList<String> FWORDS2 = new ArrayList<>(
			Arrays.asList(FWORDS));

	private static long begintime = 0;
	public static boolean isIniting = false;

	public static void init() {
		begintime = System.currentTimeMillis();
		t = new Thread(new ReadFileRunnable());
		t.start();
		isIniting = true;
	}

	private static class ReadFileRunnable implements Runnable {
		public void run() {
			try {
				readfile(INPUT_PATH);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
				ShakespeareMain.txtTips.setText("文件未找到,请重试");
			} catch (IOException e) {
				e.printStackTrace();
				ShakespeareMain.txtTips.setText("文件输入错误,请重试");
			}
			// System.out.println(wordslist.toString());
			// for (int i = 0; i < wordslist.size(); i++) {
			// System.out.println(wordslist.get(i) + " ---> "
			// + wordsInvertedIndex.get(i).get(wordslist.get(i)));
			// }
			int n = wordslist.size();
			for (int j = 0; j < filelist.size(); j++) {
				double dd = 0d;
				for (Iterator<WordEntity> it = filewordslist.get(j).iterator(); it
						.hasNext();) {
					WordEntity we = it.next();
					int df = wordsInvertedIndex
							.get(wordslist.indexOf(we.getKey()))
							.get(we.getKey()).size();
					we.setDf(df);
					double idf = Math.log10(n / df);
					we.setIdf(idf);
					we.setWeight(we.getTfw() * we.getIdf());
					dd += we.getWeight() * we.getWeight();
				}
				fileddlist.add(Math.sqrt(dd));
			}

			// FileOutputStream out;
			// try {
			// out = new FileOutputStream(INPUT_FILETXT);
			// out.write(filelist.toString().getBytes());
			// out.close();
			// } catch (Exception e) {
			// e.printStackTrace();
			// }
			FileOutputStream out, outdict;
			try {
				out = new FileOutputStream(Shakespeare.INPUT_FILETXT);
				outdict = new FileOutputStream(Shakespeare.DICT_FILE);
				StringBuffer sb = new StringBuffer();
				for (String s : filelist) {
					sb.append(s + ",");
				}
				sb.append("\n");
				out.write((sb + "").getBytes());
				sb = new StringBuffer();
				for (Double d : fileddlist) {
					sb.append(fomatdouble(d) + ",");
				}
				sb.append("\n");
				out.write((sb + "").getBytes());
				sb = new StringBuffer();
				StringBuffer sbdict = new StringBuffer();
				for (String s : wordslist) {
					sb.append(s + ",");
					sbdict.append(s + "\n");
				}
				outdict.write((sbdict + "").getBytes());
				sb.append("\n");
				out.write((sb + "").getBytes());
				sb = new StringBuffer();
				for (ArrayList<WordEntity> aw : filewordslist) {
					for (WordEntity w : aw) {
						sb.append(w.toString() + ";");
					}
					sb.append("|");
				}
				sb.append("\n");
				out.write((sb + "").getBytes());
				sb = new StringBuffer();
				System.out.println("" + wordslist.size());
				for (int i = 0; i < wordslist.size(); i++) {
					HashMap<String, ArrayList<String>> map = wordsInvertedIndex
							.get(i);
					String letter = wordslist.get(i);
					ArrayList<String> as = map.get(letter);
					if (as == null)
						as = new ArrayList<>();
					for (String s : as) {
						sb.append(s + ",");
					}
					sb.append("\n");
					out.write((sb + "").getBytes());
					sb = new StringBuffer();
				}
				// for (HashMap<String, ArrayList<String>> map :
				// wordsInvertedIndex) {
				// for (String letter : wordslist) {
				// // System.out.println(letter);
				// ArrayList<String> as = map.get(letter);
				// if (as == null)
				// as = new ArrayList<>();
				// for (String s : as) {
				// sb.append(s + ",");
				// // out.write((s + ",").getBytes());
				// }
				// sb.append(";");
				// // out.write(";".getBytes());
				// }
				// sb.append("\n");
				// out.write((sb + "").getBytes());
				// sb = new StringBuffer();
				// // out.write(".".getBytes());
				// }
				out.write((sb + "").getBytes());

				out.close();
				outdict.close();

			} catch (Exception e) {
				e.printStackTrace();
				ShakespeareMain.txtTips.setText("文件输出错误,请重试");
			}
			System.out.println("time1 "
					+ (System.currentTimeMillis() - begintime) / 1000);
			isIniting = false;
			ShakespeareMain.setInitMod(false);
			// System.out.println(filewordslist);
		}
	}

	/**
	 * 读取某个文件夹下的所有文件
	 */
	public static boolean readfile(String filepath)
			throws FileNotFoundException, IOException {
		File file = new File(filepath);
		if (!file.isDirectory()) {
			System.out.println("文件");
			System.out.println("path=" + file.getPath());
			System.out.println("absolutepath=" + file.getAbsolutePath());
			System.out.println("name=" + file.getName());

		} else if (file.isDirectory()) {
			System.out.println("文件夹");
			String[] filelist = file.list();
			for (int i = 0; i < filelist.length; i++) {
				File readfile = new File(filepath + "/" + filelist[i]);
				if (!readfile.isDirectory()) {
					System.out.println("path=" + readfile.getPath());
					System.out.println("absolutepath="
							+ readfile.getAbsolutePath());
					System.out.println("name=" + readfile.getName());
					fileWordCount(readfile.getPath(), readfile.getName());
				} else if (readfile.isDirectory()) {
					readfile(filepath + "/" + filelist[i]);
				}
			}
		}

		return true;
	}

	private static void fileWordCount(String path, String filename)
			throws IOException {
		BufferedReader br = new BufferedReader(new FileReader(path));
		String s;
		StringBuffer sb = new StringBuffer();
		while ((s = br.readLine()) != null) {
			sb.append(s);
		}
		Map<String, Integer> map = new HashMap<String, Integer>();
		StringTokenizer st = new StringTokenizer(sb.toString(), DELIM);
		while (st.hasMoreTokens()) {
			String letter = st.nextToken();
			letter = letter.toLowerCase();
			// 去除一些不必要的词
			if (FWORDS2.lastIndexOf(letter) != -1)
				continue;
			cutword(letter);
			int count;
			if (map.get(letter) == null) {
				count = 1;
			} else {
				count = map.get(letter).intValue() + 1;
			}
			map.put(letter, count);
			int index = wordslist.lastIndexOf(letter);
			// System.out.println(letter + "   " + index);
			if (index != -1) {
				ArrayList<String> a = wordsInvertedIndex.get(index).get(letter);
				if (!a.contains(filename))
					a.add(filename);
			} else {
				wordslist.add(letter);
				HashMap<String, ArrayList<String>> map1 = new HashMap<>();
				ArrayList<String> a1 = new ArrayList<>();
				a1.add(filename);
				map1.put(letter, a1);
				wordsInvertedIndex.add(map1);
			}
		}
		ArrayList<WordEntity> arr = new ArrayList<WordEntity>();
		for (String key : map.keySet()) {
			arr.add(new WordEntity(key, map.get(key), map.get(key), 1 + Math
					.log10(map.get(key))));
		}
		filelist.add(filename);
		filewordslist.add(arr);
		// Set<WordEntity> set = new TreeSet<WordEntity>();
		// for (String key : map.keySet()) {
		// set.add(new WordEntity(key, map.get(key)));
		// }
		// // 自己拼接字符串，输出我们想要的字符串格式
		// for (Iterator<WordEntity> it = set.iterator(); it.hasNext();) {
		// WordEntity w = it.next();
		// System.out.println("单词:" + w.getKey() + " 出现的次数为： "
		// + w.getCount());
		// }

	}

	public static void cutword(String s) {
		if (s.length() < 4)
			return;
		if (s.endsWith("ing")) {
			s.substring(s.length() - 3);
		} else if (s.endsWith("s")) {
			s.substring(s.length() - 1);
		} else if (s.endsWith("es")) {
			s.substring(s.length() - 2);
		} else if (s.endsWith("d")) {
			s.substring(s.length() - 1);
		} else if (s.endsWith("ed")) {
			s.substring(s.length() - 2);
		}
	}

	public static String fomatdouble(Double d) {
		DecimalFormat df = new DecimalFormat("#.00");
		return "" + df.format(d);
	}
}
